home *** CD-ROM | disk | FTP | other *** search
/ Mission 3 / Mission 3.zip / Mission 3.iso / texte / qed / src / block.c < prev    next >
C/C++ Source or Header  |  1998-06-30  |  20KB  |  991 lines

  1. #include <support.h>
  2.  
  3. #include "global.h"
  4. #include "clipbrd.h"
  5. #include "edit.h"
  6. #include "memory.h"
  7. #include "options.h"
  8. #include "rsc.h"
  9. #include "set.h"
  10. #include "block.h"
  11.  
  12. /* lokale Prototypen *******************************************************/
  13. static void    block_demark    (TEXTP t_ptr);
  14. static bool    tab_ok            (ZEILEP a, bool tab, int tabsize);
  15. static void    block_setzen    (TEXTP t_ptr);
  16. static bool    block_delete    (TEXTP t_ptr, RINGP t);
  17. static bool    block_einsetzen(TEXTP t_ptr, RINGP t);
  18.  
  19. /* lokale Variablen ********************************************************/
  20.  
  21. static int    undo_anf_x, undo_end_x;
  22. static long    undo_anf_y, undo_end_y;
  23. static RING    trash_text;
  24. static bool    trash_init = FALSE;
  25.  
  26. /*
  27.  * Trash: Puffer für selektierte Blöcke, die überschrieben wurden. 
  28. */
  29. static void trash_takes_text(RINGP r)
  30. {
  31.     if (!trash_init)
  32.     {
  33.         init_textring(&trash_text);
  34.         trash_init = TRUE;
  35.     }
  36.  
  37.     kill_textring(&trash_text);
  38.     trash_text = *r;
  39.     FIRST(r)->vorg = &trash_text.head;
  40.     LAST(r)->nachf = &trash_text.tail;
  41. }
  42.  
  43. /***************************************************************************/
  44.  
  45. void blk_mark_all(TEXTP t_ptr)
  46. {
  47.     ZEILEP col;
  48.  
  49.     if (t_ptr->block)
  50.         block_demark(t_ptr);
  51.     col = FIRST(&t_ptr->text);
  52.     t_ptr->x1 = 0;
  53.     t_ptr->p1 = col;
  54.     t_ptr->z1 = 0;
  55.     col = LAST(&t_ptr->text);
  56.     t_ptr->x2 = col->len;
  57.     t_ptr->p2 = col;
  58.     t_ptr->z2 = t_ptr->text.lines-1;
  59.     t_ptr->block_dir = FALSE;            /* Anfang und Ende nicht vertauscht */
  60.     block_setzen(t_ptr);
  61.     make_chg(t_ptr->link,BLK_CHANGE,0);
  62.     make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z2);
  63. }
  64.  
  65.  
  66. void blk_mark_word(TEXTP t_ptr)        /* Wort unter dem Cursor markieren */
  67. {
  68.     int    pos,len;
  69.     char    *str;
  70.  
  71.     pos = t_ptr->xpos;
  72.     len = t_ptr->cursor_line->len;
  73.     if (pos < len)
  74.     {
  75.         str = TEXT(t_ptr->cursor_line)+pos;
  76.         while(pos >= 0 && setin(t_ptr->loc_opt->wort_set, *str))
  77.         {
  78.             pos--;
  79.             str--;
  80.         }
  81.         if (pos != t_ptr->xpos)
  82.         {
  83.             str++; 
  84.             pos++;
  85.             t_ptr->xpos = pos;
  86.         }
  87.         blk_mark(t_ptr, 0);
  88.         while(pos <= len && setin(t_ptr->loc_opt->wort_set, *str))
  89.         {
  90.             pos++;
  91.             str++;
  92.         }
  93.         t_ptr->xpos = pos;
  94.         blk_mark(t_ptr, 1);
  95.         restore_edit();
  96.     }
  97. }
  98.  
  99.  
  100. static void search_forw(TEXTP t_ptr, char b_1, char b_2)    /* Klammersuche vorwärts */
  101. {
  102.     ZEILEP    lauf;
  103.     int        x, level = 0, i;
  104.     long        y;
  105.     bool    found = FALSE;
  106.     
  107.     lauf = t_ptr->cursor_line;
  108.     x = t_ptr->xpos;
  109.     y = t_ptr->ypos;
  110.  
  111.     /* Trick für identische b1/b2 (z.B. ") */
  112.     if (b_1 == b_2)
  113.     {
  114.         level = 2;
  115.         b_1 = '\0';
  116.     }
  117.     do
  118.     {
  119.         for (i = x; i < lauf->len; i++)
  120.         {
  121.             if (TEXT(lauf)[i] == b_1)
  122.                 level++;
  123.             else if (TEXT(lauf)[i] == b_2)
  124.                 level--;
  125.             if (level == 0)
  126.             {
  127.                 x = i + 1;
  128.                 found = TRUE;
  129.                 break;
  130.             }
  131.         }
  132.         if (!found)
  133.         {
  134.             NEXT(lauf);
  135.             y++;
  136.             x = 0;
  137.         }
  138.     }
  139.     while (!found && !IS_TAIL(lauf));
  140.     if (found)
  141.     {
  142.         t_ptr->cursor_line = lauf;
  143.         t_ptr->xpos = x;
  144.         t_ptr->ypos = y;
  145.     }
  146.     else
  147.         Bconout(2, 7);
  148. }
  149.  
  150. static void search_backw(TEXTP t_ptr, char b_1, char b_2)    /* Klammersuche rückw. */
  151. {
  152.     ZEILEP    lauf;
  153.     int        x, level = 0, i;
  154.     long        y;
  155.     bool    found = FALSE;
  156.     
  157.     lauf = t_ptr->cursor_line;
  158.     x = t_ptr->xpos;
  159.     y = t_ptr->ypos;
  160.     do
  161.     {
  162.         for (i = x; i >= 0; i--)        
  163.         {
  164.             if (TEXT(lauf)[i] == b_1)
  165.                 level++;
  166.             else if (TEXT(lauf)[i] == b_2)
  167.                 level--;
  168.             if (level == 0)
  169.             {
  170.                 x = i;
  171.                 found = TRUE;
  172.                 break;
  173.             }
  174.         }
  175.         if (!found)
  176.         {
  177.             VORG(lauf);
  178.             y--;
  179.             x = lauf->len-1;
  180.         }
  181.     }
  182.     while (!found && !IS_HEAD(lauf));
  183.     if (found)
  184.     {
  185.         t_ptr->cursor_line = lauf;
  186.         t_ptr->xpos = x;
  187.         t_ptr->ypos = y;
  188.     }
  189.     else
  190.         Bconout(2, 7);
  191. }
  192.  
  193. bool blk_mark_brace(TEXTP t_ptr)
  194. {
  195.     bool    found = FALSE;
  196.     char        c, *p;
  197.     int        index;
  198.         
  199.     if (t_ptr->xpos < t_ptr->cursor_line->len)
  200.     {
  201.         c = TEXT(t_ptr->cursor_line)[t_ptr->xpos];
  202.         p = strchr(klammer_auf, c);
  203.         if (p)
  204.         {
  205.             index = (int)(p - klammer_auf);
  206.             blk_mark(t_ptr, 0);
  207.             search_forw(t_ptr, klammer_auf[index], klammer_zu[index]);
  208.             blk_mark(t_ptr, 1);
  209.             found = TRUE;
  210.         }
  211.         p = strchr(klammer_zu, c);
  212.         if (!found && p)
  213.         {
  214.             index = (int)(p - klammer_zu);
  215.             /*
  216.              * der Cursor steht auf der Klammer, muß aber dahinter stehen, damit 
  217.              * sie auch selektiert wird!
  218.              */
  219.             t_ptr->xpos += 1;            
  220.             blk_mark(t_ptr, 0);     
  221.             t_ptr->xpos -= 1;
  222.             search_backw(t_ptr, klammer_auf[index], klammer_zu[index]);
  223.             blk_mark(t_ptr, 1);
  224.             found = TRUE;
  225.         }
  226.     }
  227.     return found;
  228. }
  229.  
  230.  
  231. void get_blk_mark(TEXTP t_ptr, long *y, int *x)
  232. {
  233.     if (t_ptr->block_dir)    /* nach links */
  234.     {
  235.         *y = t_ptr->z2;
  236.         *x = t_ptr->x2;
  237.     }
  238.     else                            /* nach rechts */
  239.     {
  240.         *y = t_ptr->z1;
  241.         *x = t_ptr->x1;
  242.     }
  243. }
  244.  
  245. void blk_mark(TEXTP t_ptr, int marke)
  246. /* Blockstart und -ende setzen    */
  247. /* marke : 0 und 1                    */
  248. {
  249.     if (marke == 0)    /* Anfang setzten */
  250.     {
  251.         blk_demark(t_ptr);
  252.         t_ptr->p2 = t_ptr->p1 = t_ptr->cursor_line;
  253.         t_ptr->z2 = t_ptr->z1 = t_ptr->ypos;
  254.         t_ptr->x2 = t_ptr->x1 = t_ptr->xpos;
  255.         t_ptr->block_dir = FALSE;
  256.     }
  257.     else                /* Block aufziehen */
  258.     {
  259.         if (t_ptr->block_dir)
  260.         {
  261.             if (t_ptr->p1 == t_ptr->cursor_line && t_ptr->x1 == t_ptr->xpos)
  262.                 return;                                /* Keine Änderung */
  263.             if (t_ptr->block)
  264.             {
  265.                 block_demark(t_ptr);
  266.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z1);
  267.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->ypos);
  268.             }
  269.             else
  270.             {
  271.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->ypos);
  272.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z2);
  273.             }
  274.             t_ptr->p1 = t_ptr->cursor_line;
  275.             t_ptr->x1 = t_ptr->xpos;
  276.             t_ptr->z1 = t_ptr->ypos;
  277.         }
  278.         else
  279.         {
  280.             if (t_ptr->p2==t_ptr->cursor_line && t_ptr->x2==t_ptr->xpos)
  281.                 return;                                /* Keine Änderung */
  282.             if (t_ptr->block)
  283.             {
  284.                 block_demark(t_ptr);
  285.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z2);
  286.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->ypos);
  287.             }
  288.             else
  289.             {
  290.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z1);
  291.                 make_chg(t_ptr->link,BLK_CHANGE,t_ptr->ypos);
  292.             }
  293.             t_ptr->p2 = t_ptr->cursor_line;
  294.             t_ptr->x2 = t_ptr->xpos;
  295.             t_ptr->z2 = t_ptr->ypos;
  296.         }
  297.         block_setzen(t_ptr);
  298.     }
  299. }
  300.  
  301.  
  302. void blk_demark(TEXTP t_ptr)
  303. {
  304.     if (t_ptr->block)
  305.     {
  306.         block_demark(t_ptr);
  307.         make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z1);
  308.         make_chg(t_ptr->link,BLK_CHANGE,t_ptr->z2);
  309.         t_ptr->p1 = t_ptr->p2 = NULL;
  310.         t_ptr->z1 = t_ptr->z2 = -1;
  311.     }
  312. }
  313.  
  314.  
  315. void blk_copy(TEXTP t_ptr)
  316. /* Kopiert Block aus einem Text auf das Clipbrd */
  317. {
  318.     RING t;
  319.  
  320.     if (!t_ptr->block)
  321.         return;
  322.     if (!ist_mem_frei())
  323.         return;
  324.     block_copy(t_ptr,&t);
  325.     if (shift_pressed())
  326.         clip_add_text(&t);
  327.     else
  328.         clip_takes_text(&t);
  329. }
  330.  
  331. void line_copy(TEXTP t_ptr)
  332. /* Kopiert aktuelle Zeile auf das Clipboard */
  333. {
  334.     ZEILEP    col = t_ptr->cursor_line;
  335.     int    old_x;
  336.  
  337.     old_x = t_ptr->xpos;
  338.     t_ptr->xpos = 0;
  339.     blk_mark(t_ptr,0);
  340.     if (IS_LAST(col))
  341.     {
  342.         t_ptr->xpos = col->len;
  343.         blk_mark(t_ptr,1);
  344.         t_ptr->xpos = old_x;
  345.     }
  346.     else
  347.     {
  348.         NEXT(col);
  349.         t_ptr->cursor_line = col;
  350.         blk_mark(t_ptr,1);
  351.         VORG(col);
  352.         t_ptr->cursor_line = col;
  353.         t_ptr->xpos = old_x;
  354.     }
  355.     blk_copy(t_ptr);
  356.     blk_demark(t_ptr);
  357. }
  358.  
  359. void blk_paste(TEXTP t_ptr, RINGP t)
  360. /* Setzt den Text t im Text an Cursorposition ein */
  361. /* Der Cursor steht anschließend dahinter */
  362. /* Ist ein Block da, wird er gelöscht */
  363. {
  364.     if (!ist_mem_frei())
  365.         return;
  366.     blk_delete(t_ptr);
  367.     block_einsetzen(t_ptr, t);
  368.     t_ptr->moved++;
  369.     add_undo(BLK_PASTE);
  370. }
  371.  
  372. void blk_delete(TEXTP t_ptr)
  373. {
  374.     RING t;
  375.  
  376.     if(!t_ptr->block)
  377.         return;
  378.     if (!ist_mem_frei())
  379.         return;
  380.     if (!block_delete(t_ptr, &t))
  381.         return;
  382.     trash_takes_text(&t);
  383.     t_ptr->moved++;
  384.     add_undo(BLK_DEL);
  385. }
  386.  
  387. void blk_cut(TEXTP t_ptr)
  388. {
  389.     RING t, t2;
  390.  
  391.     if (!t_ptr->block)
  392.         return;
  393.     if (!ist_mem_frei())
  394.         return;
  395.     if (!block_delete(t_ptr, &t))
  396.         return;
  397.     init_textring(&t2);
  398.     if (doppeln(&t,&t2))
  399.     {
  400.         if (shift_pressed())
  401.             clip_add_text(&t2);
  402.         else
  403.             clip_takes_text(&t2);
  404.     }
  405.     undo_takes_text(&t);
  406.     t_ptr->moved++;
  407.     add_undo(BLK_CUT);
  408. }
  409.  
  410. void blk_undo(TEXTP t_ptr, int undo)
  411. {
  412.     RING    t;
  413.  
  414.     if (!ist_mem_frei())
  415.         return;
  416.     if (undo==BLK_PASTE || undo==BLK_PASTE_TRASH)
  417.     /* Block muß wieder gelöscht werden */
  418.     {
  419.         blk_demark(t_ptr);
  420.         t_ptr->p1 = get_line(&t_ptr->text,undo_anf_y);
  421.         t_ptr->z1 = undo_anf_y;
  422.         t_ptr->x1 = undo_anf_x;
  423.         t_ptr->p2 = get_line(&t_ptr->text,undo_end_y);
  424.         t_ptr->z2 = undo_end_y;
  425.         t_ptr->x2 = undo_end_x;
  426.         block_setzen(t_ptr);
  427.         block_delete(t_ptr, &t);                /* Block ausschneiden und als Undotext */
  428.         if (undo==BLK_PASTE)
  429.         {
  430.             undo_takes_text(&t);
  431.             add_undo(BLK_CUT);
  432.         }
  433.         else
  434.         {
  435.             trash_takes_text(&t);
  436.             add_undo(BLK_DEL);
  437.         }
  438.         t_ptr->moved++;
  439.     }
  440.     if (undo == BLK_CUT)                            /* Block muß wieder eingefügt werden */
  441.     {
  442.         RINGP tp;
  443.  
  444.         t_ptr->xpos = undo_anf_x;
  445.         tp = get_undo_text();
  446.         block_einsetzen(t_ptr, tp);
  447.         add_undo(BLK_PASTE);
  448.     }
  449.     if (undo==BLK_DEL)                            /* Text aus Papierkorb wieder einsetzten */
  450.     {
  451.  
  452.         t_ptr->xpos = undo_anf_x;
  453.         block_einsetzen(t_ptr, &trash_text);
  454.         add_undo(BLK_PASTE_TRASH);
  455.     }
  456. }
  457.  
  458. void blk_right(TEXTP t_ptr)
  459. {
  460.     ZEILEP     lauf;
  461.     long        y, ende;
  462.     bool    t = t_ptr->loc_opt->tab;
  463.  
  464.     if (!t_ptr->block)
  465.         return;
  466.     lauf = t_ptr->p1;
  467.     y = t_ptr->z1;
  468.     ende = t_ptr->z2;
  469.     if (y < ende)
  470.     {
  471.         int  anz, i;
  472.         char    c, *str;
  473.  
  474.         if (shift_pressed())        /* mit Shift: nur ein ' ' */
  475.         {
  476.             anz = 1;
  477.             c = ' ';
  478.         }
  479.         else
  480.         {    
  481.             if (t)
  482.             {
  483.                 anz = 1;
  484.                 c = '\t';
  485.             }
  486.             else
  487.             {
  488.                 anz = t_ptr->loc_opt->tabsize;
  489.                 c = ' ';
  490.             }
  491.         }
  492.         t_ptr->moved++;
  493.         clr_undo();
  494.         if (t_ptr->x1>0) t_ptr->x1 += anz;
  495.         while (y<ende || t_ptr->x2>0)
  496.         {
  497.             if (lauf->len+anz>MAX_LINE_LEN)
  498.             {
  499.                 inote(1, 0, TOOLONG, MAX_LINE_LEN);
  500.                 break;
  501.             }
  502.             str = REALLOC(&lauf,0,anz);
  503.             for (i=anz; (--i)>=0; )
  504.                 *str++ = c;
  505.             if (y==t_ptr->z1)
  506.                 t_ptr->p1 = lauf;
  507.             if (y==ende)
  508.             {
  509.                 t_ptr->p2 = lauf;
  510.                 break;
  511.             }
  512.             NEXT(lauf);
  513.             y++;
  514.         }
  515.         if (t_ptr->x2>0) t_ptr->x2 += anz;
  516.         t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  517.         make_chg(t_ptr->link,TOTAL_CHANGE,t_ptr->z1);
  518.     }
  519. }
  520.  
  521. void blk_left(TEXTP t_ptr)
  522. {
  523.     ZEILEP     lauf;
  524.     long        y, ende;
  525.     bool    t = t_ptr->loc_opt->tab;
  526.     int        ts = t_ptr->loc_opt->tabsize;
  527.  
  528.     if (!t_ptr->block)
  529.         return;
  530.     lauf = t_ptr->p1;
  531.     y = t_ptr->z1;
  532.     ende = t_ptr->z2;
  533.     if (y < ende)
  534.     {
  535.         int anz;
  536.  
  537.         if (shift_pressed())
  538.         {
  539.             anz = ts = 1;
  540.             t = FALSE;
  541.         }
  542.         else
  543.         {
  544.             if (t)
  545.                 anz = 1;
  546.             else
  547.                 anz = ts;
  548.         }        
  549.         t_ptr->moved++;
  550.         clr_undo();
  551.         if (tab_ok(lauf,t,ts))
  552.         {
  553.             if (t_ptr->x1 <= anz)
  554.                 t_ptr->x1 = 0;
  555.             else
  556.                 t_ptr->x1 -= anz;
  557.         }
  558.         while (y < ende || t_ptr->x2 > 0)
  559.         {
  560.             if (tab_ok(lauf,t,ts))
  561.             {
  562.                 REALLOC(&lauf, 0, -anz);
  563.                 if (y == t_ptr->z1)
  564.                     t_ptr->p1 = lauf;
  565.                 if (y == ende)
  566.                     t_ptr->p2 = lauf;
  567.             }
  568.             if (y == ende)
  569.                 break;
  570.             NEXT(lauf);
  571.             y++;
  572.         }
  573.         if (tab_ok(lauf,t,ts))
  574.         {
  575.             if (t_ptr->x2 <= anz)
  576.                 t_ptr->x2 = 0;
  577.             else
  578.                 t_ptr->x2 -= anz;
  579.         }
  580.         t_ptr->cursor_line = get_line(&t_ptr->text, t_ptr->ypos);
  581.         make_chg(t_ptr->link, POS_CHANGE, 0);
  582.         make_chg(t_ptr->link, TOTAL_CHANGE, t_ptr->z1);
  583.     }
  584. }
  585.  
  586. /*-------------------------------------------------------------------*/
  587.  
  588. void str_ch_uprlwr (char *line)
  589. {
  590.     char stra[2],strb[2];
  591.  
  592.     stra[1] = strb[1] = EOS;
  593.  
  594.     while (*line != EOS)
  595.     {
  596.         stra[0] = *line;
  597.         strb[0] = *line;
  598.         str_toupper(stra);
  599.         str_tolower(strb);
  600.         if (stra[0] == *line)
  601.             *line = strb[0];
  602.         else
  603.             *line = stra[0];
  604.  
  605.         line++;
  606.     }
  607. }
  608.  
  609. void strcap (char *line, SET wort_set)
  610. {
  611.     char stra[2],strb[2];
  612.  
  613.     stra[1] = strb[1] = EOS;
  614.     stra[0] = *line;
  615.     if (setin(wort_set,stra[0]))
  616.     {
  617.         str_toupper(stra);
  618.         *line=stra[0];
  619.     }
  620.     line++;
  621.     while (*line != EOS)
  622.     {
  623.         strb[0] = *(line-1);
  624.         if (!setin(wort_set,strb[0]))
  625.         {
  626.             stra[0] = *line;
  627.             if (setin(wort_set,stra[0]))
  628.             {
  629.                 str_toupper(stra);
  630.                 *line=stra[0];
  631.             }
  632.         }
  633.         line++;
  634.     }
  635. }
  636.  
  637. void blk_upplow(TEXTP t_ptr, int type)
  638. {
  639.     ZEILEP    lauf;
  640.     long    y, ende;
  641.  
  642.     if (!t_ptr->block)
  643.         return;
  644.  
  645.     lauf = t_ptr->p1;
  646.     y = t_ptr->z1;
  647.     ende = t_ptr->z2;
  648.     if (y <= ende)
  649.     {
  650.         char *Tline, c;
  651.  
  652.         t_ptr->moved++;
  653.         clr_undo();
  654.         while (y < ende || t_ptr->x2 > 0)
  655.         {
  656.             if (y == t_ptr->z1)
  657.                 Tline = TEXT(lauf)+t_ptr->x1;
  658.             else
  659.                 Tline = TEXT(lauf);
  660.             if (y == ende)
  661.             {
  662.                 c = *(TEXT(lauf)+t_ptr->x2);
  663.                 *(TEXT(lauf)+t_ptr->x2) = EOS; /* Zeile unterbrechen */
  664.             }
  665.             switch (type)
  666.             {
  667.                 case BLK_UPPER:
  668.                     str_toupper (Tline);
  669.                     break;
  670.                 case BLK_LOWER :
  671.                     str_tolower (Tline);
  672.                     break;
  673.                 case BLK_CH_UPLO :
  674.                     str_ch_uprlwr (Tline);
  675.                     break;
  676.                 case BLK_CAPS :
  677.                     str_tolower (Tline);
  678.                     strcap (Tline,t_ptr->loc_opt->wort_set);
  679.                     break;
  680.             }
  681.             if (y == ende)
  682.             {
  683.                 *(TEXT(lauf)+t_ptr->x2) = c; /* Zeile restaurieren */
  684.                 break;
  685.             }
  686.             NEXT(lauf);
  687.             y++;
  688.         }
  689.         t_ptr->moved++;
  690.         make_chg(t_ptr->link, POS_CHANGE, 0);
  691.         make_chg(t_ptr->link, TOTAL_CHANGE, t_ptr->z1);
  692.     }
  693. }
  694.  
  695. /*----------------------------------------------------------------*/
  696.  
  697. static void block_demark(TEXTP t_ptr)
  698. {
  699.     t_ptr->block = FALSE;
  700.     t_ptr->cursor = TRUE;
  701. }
  702.  
  703. static bool tab_ok(ZEILEP a, bool tab, int tabsize)
  704. {
  705.     int     anz;
  706.     char *str;
  707.  
  708.     if (tab)
  709.     {
  710.         if (a->len==0) return(FALSE);
  711.         str = TEXT(a);
  712.         if (*str!='\t') return(FALSE);
  713.     }
  714.     else
  715.     {
  716.         anz = tabsize;
  717.         if (a->len<anz) return(FALSE);
  718.         str = TEXT(a);
  719.         while ((--anz)>=0)
  720.         {
  721.             if (*str++!=' ') return(FALSE);
  722.         }
  723.     }
  724.     return(TRUE);
  725. }
  726.  
  727. static void block_setzen(TEXTP t_ptr)
  728. {
  729.     if (t_ptr->p1 == t_ptr->p2 && t_ptr->x1 == t_ptr->x2)
  730.         return;
  731.  
  732.     if (t_ptr->z1 > t_ptr->z2)            /* Richtung falsch => tauschen */
  733.     {
  734.         ZEILEP col;
  735.         long    l;
  736.         int    i;
  737.  
  738.         t_ptr->block_dir ^= TRUE;
  739.         i = t_ptr->x1;
  740.         t_ptr->x1 = t_ptr->x2;
  741.         t_ptr->x2 = i;
  742.         col = t_ptr->p1;
  743.         t_ptr->p1 = t_ptr->p2;
  744.         t_ptr->p2 = col;
  745.         l = t_ptr->z1;
  746.         t_ptr->z1 = t_ptr->z2;
  747.         t_ptr->z2 = l;
  748.     }
  749.     else if (t_ptr->z1 == t_ptr->z2 && t_ptr->x1 > t_ptr->x2)
  750.     {
  751.         int xw;
  752.  
  753.         t_ptr->block_dir ^= TRUE;
  754.         xw = t_ptr->x1;
  755.         t_ptr->x1 = t_ptr->x2;
  756.         t_ptr->x2 = xw;
  757.     }
  758.     t_ptr->block = TRUE;
  759.     t_ptr->cursor = FALSE;
  760. }
  761.  
  762. static bool block_delete(TEXTP t_ptr, RINGP t)
  763. {
  764.     ZEILEP b_anf_col, b_end_col;
  765.     long    lines;
  766.  
  767.     b_anf_col = t_ptr->p1;
  768.     b_end_col = t_ptr->p2;
  769.     if (b_end_col->len-t_ptr->x2+t_ptr->x1>MAX_LINE_LEN)
  770.     {
  771.         inote(1, 0, TOOLONG, MAX_LINE_LEN);
  772.         return(FALSE);
  773.     }
  774.  
  775.     /* Cursor an den Blockanfang bringen */
  776.     t_ptr->ypos = t_ptr->z1;
  777.     t_ptr->xpos = t_ptr->x1;
  778.  
  779.     undo_anf_y = t_ptr->z1;
  780.     undo_anf_x = t_ptr->x1;
  781.     undo_y = t_ptr->ypos;                /* globale Merkvariable */
  782.  
  783.     lines = t_ptr->z2-t_ptr->z1+1;
  784.     if (lines==1)                            /* ganz ohne Zeilenumbruch */
  785.     {
  786.         int len = t_ptr->x2-t_ptr->x1;
  787.         ZEILEP    b;
  788.  
  789.         init_textring(t);
  790.         b = FIRST(t);
  791.         INSERT(&b, 0, len, TEXT(b_anf_col)+t_ptr->x1);
  792.         REALLOC(&b_anf_col, t_ptr->x1, -len);
  793.         t_ptr->cursor_line = b_anf_col;
  794.     }
  795.     else
  796.     {
  797.         col_split(&b_end_col,t_ptr->x2);
  798.         NEXT(b_end_col);
  799.         col_split(&b_anf_col,t_ptr->x1);
  800.  
  801.         /* Block ausschneiden */
  802.         FIRST(t) = b_anf_col->nachf;
  803.         b_anf_col->nachf->vorg = &t->head;
  804.         LAST(t) = b_end_col->vorg;
  805.         b_end_col->vorg->nachf = &t->tail;
  806.         t->lines = lines;
  807.  
  808.         /* Kette wieder schließen */
  809.         b_anf_col->nachf = b_end_col;
  810.         b_end_col->vorg = b_anf_col;
  811.         col_concate(&b_anf_col);
  812.         t_ptr->cursor_line = b_anf_col;
  813.     }
  814. #if 0
  815. Problem: Wenn ein Block markiert war, muß eventuell gescrollt werden
  816.          und es kommt zu Redraw-Fehlern, da doch mehr Zeilen betroffen sind!
  817.  
  818.     if (lines==1)
  819.     {
  820.         make_chg(t_ptr->link,POS_CHANGE, 0);
  821.         make_chg(t_ptr->link,LINE_CHANGE, undo_y);
  822.     }
  823.     else if (lines==2)
  824.     {
  825.         make_chg(t_ptr->link,POS_CHANGE, 0);
  826.         make_chg(t_ptr->link,LINE_CHANGE, undo_y);
  827.         make_chg(t_ptr->link,SCROLL_UP, undo_y+1);
  828.     }
  829.     else
  830. #endif
  831.     {
  832.         make_chg(t_ptr->link,POS_CHANGE, 0);
  833.         make_chg(t_ptr->link,TOTAL_CHANGE,t_ptr->z1);
  834.     }
  835.     t_ptr->block = FALSE;
  836.     t_ptr->cursor = TRUE;
  837.     t_ptr->text.lines -= (lines-1);
  838.     t->ending = t_ptr->text.ending;
  839.     t->max_line_len = t_ptr->text.max_line_len;
  840.     t_ptr->max_line = NULL;
  841.     return TRUE;
  842. }
  843.  
  844. void block_copy(TEXTP t_ptr, RINGP t)
  845. {
  846.     ZEILEP a, lauf;
  847.  
  848.     init_textring(t);
  849.     a = FIRST(t);                                    /* erste Zeile */
  850.     lauf = t_ptr->p1;                                /* Blockstart */
  851.     if (lauf == t_ptr->p2)                        /* nur eine Zeile */
  852.     {
  853.         INSERT(&a, 0, t_ptr->x2-t_ptr->x1, TEXT(lauf)+t_ptr->x1);
  854.         a->info |= ABSATZ;
  855.     }
  856.     else
  857.     {
  858.         ZEILEP new, ende;
  859.  
  860.         /* erste Zeile teilweise */
  861.         INSERT(&a, 0, lauf->len-t_ptr->x1, TEXT(lauf)+t_ptr->x1);
  862.         if (IS_ABSATZ(lauf)) 
  863.             a->info |= ABSATZ;
  864.         else 
  865.             a->info &= (~ABSATZ);
  866.         ende = t_ptr->p2;
  867.         NEXT(lauf);
  868.         NEXT(a);                                                    /* TAIL im neuen Text */
  869.         while (lauf != ende)
  870.         {
  871.             new = new_col(TEXT(lauf), lauf->len);
  872.             if (IS_ABSATZ(lauf)) 
  873.                 new->info |= ABSATZ;
  874.             col_insert(a->vorg,new);
  875.             t->lines++;
  876.             NEXT(lauf);
  877.         }
  878.         new = new_col(TEXT(lauf),t_ptr->x2);            /* letzte Zeile teilweise */
  879.         new->info |= ABSATZ;
  880.         col_insert(a->vorg,new);
  881.         t->lines++;
  882.     }
  883.     t->ending = t_ptr->text.ending;
  884.     t->max_line_len = t_ptr->text.max_line_len;
  885. }
  886.  
  887. /* Der Cursor von t_ptr steht anschließend hinter der Einfügung */
  888. static bool block_einsetzen(TEXTP t_ptr, RINGP in)
  889. {
  890.     RING    t;
  891.     ZEILEP    a,b,
  892.             col = t_ptr->cursor_line;
  893.     long    len;
  894.  
  895.     a = FIRST(in);
  896.     b = LAST(in);
  897.     if ((a!=b &&
  898.           (t_ptr->xpos+a->len>MAX_LINE_LEN ||
  899.             b->len+(col->len-t_ptr->xpos)>MAX_LINE_LEN)) ||
  900.          (a==b &&
  901.           col->len+a->len>MAX_LINE_LEN))
  902.     {
  903.         inote(1, 0, TOOLONG, MAX_LINE_LEN);
  904.         return(FALSE);
  905.     }
  906.  
  907.     init_textring(&t);
  908.     doppeln(in, &t);
  909.     a = FIRST(&t);
  910.     b = LAST(&t);
  911.  
  912. #if 0
  913. Problem: Wenn ein Block markiert war, muß eventuell gescrollt werden
  914.          und es kommt zu Redraw-Fehlern, da doch mehr Zeilen betroffen sind!
  915.          
  916.     if (t.lines==1)            /* Ganz ohne Zeilenveränderung */
  917.         make_chg(t_ptr->link,LINE_CHANGE,t_ptr->ypos);
  918.     else if(t.lines==2)        /* Einen Zeilenumbruch */
  919.     {
  920.         make_chg(t_ptr->link,SCROLL_DOWN,t_ptr->ypos+1);
  921.         make_chg(t_ptr->link,LINE_CHANGE,t_ptr->ypos);
  922.         make_chg(t_ptr->link,LINE_CHANGE,t_ptr->ypos+1);
  923.     }
  924.     else
  925. #endif
  926.         make_chg(t_ptr->link,TOTAL_CHANGE,t_ptr->ypos);
  927.  
  928.     len = t.lines-1;
  929.     t_ptr->text.lines += len;
  930.  
  931.     undo_anf_y = t_ptr->ypos;
  932.     undo_anf_x = t_ptr->xpos;
  933.     undo_end_y = undo_anf_y+len;
  934.     undo_end_x = b->len;
  935.     undo_y = t_ptr->ypos;                                /* globale Merkvariable */
  936.     if (len==0)
  937.     {
  938.         INSERT(&col, t_ptr->xpos, a->len, TEXT(a));
  939.         undo_end_x += t_ptr->xpos;
  940.         kill_textring(&t);
  941.     }
  942.     else
  943.     {
  944.         col_split(&col,t_ptr->xpos);                    /* Textzeile splitten   */
  945.  
  946.         col->nachf->vorg = b;                            /* Block einfügen unten */
  947.         b->nachf = col->nachf;
  948.         col_concate(&b);                                    /* Untere letzte Zeile    */
  949.  
  950.         col->nachf = a;                                    /* Block einfügen oben */
  951.         a->vorg = col;
  952.         col_concate(&col);
  953.     }
  954.     /* Cursor hinter Einfügung */
  955.     t_ptr->cursor_line = get_line(&t_ptr->text,undo_end_y);
  956.     t_ptr->ypos = undo_end_y;
  957.     t_ptr->xpos = undo_end_x;
  958.     t_ptr->moved++;
  959.     make_chg(t_ptr->link, POS_CHANGE, 0);
  960.     t_ptr->max_line = NULL;
  961.     return TRUE;
  962. }
  963.  
  964.  
  965. /*
  966.  * Dialog(e)
  967. */
  968. void    block_info(TEXTP t_ptr)
  969. {
  970.     char    str[30];
  971.     RING    t;
  972.  
  973.     block_copy(t_ptr,&t);
  974.     if (t_ptr->x1 == 0 && t_ptr->x2 == 0)
  975.         t.lines -= 1;
  976.  
  977.     make_shortpath(t_ptr->filename, str, 30);
  978.     set_string(blockinfo, BLONAME, str);                    /* Name mit Pfad */
  979.  
  980.     set_long(blockinfo, BLOBYTES, textring_bytes(&t));    /* Größe in Bytes */
  981.  
  982.     if (t_ptr->text.ending != binmode)
  983.         set_long(blockinfo, BLOZEILE, t.lines);
  984.     else
  985.         set_string(blockinfo, BLOZEILE, "--");        /* Binär: keine Zeilen */
  986.  
  987.     simple_mdial(blockinfo, 0);
  988.  
  989.     kill_textring(&t);
  990. }
  991.